/** @file alias_vec.h
 *
 *  @author Dongryeol Lee (drselee@gmail.com)
 */

#ifndef CORE_DATA_ALIAS_VEC_H
#define CORE_DATA_ALIAS_VEC_H

#include <armadillo>

namespace core {
namespace data {
class alias_vec {
  private:

    double *v_;

    arma::uvec *indices_;

  public:

    int size() const {
      return static_cast<int>(indices_->n_elem);
    }

    alias_vec() {
      v_ = NULL;
      indices_ = NULL;
    }

    alias_vec(arma::vec &v_in, arma::uvec &indices_in) {
      v_ = v_in.memptr();
      indices_ = &indices_in;
    }

    double &operator[](int index_in) {
      return v_[indices_->at(index_in)];
    }

    const double &operator[](int index_in) const {
      return v_[indices_->at(index_in)];
    }
};
}
}

namespace arma {
template<typename T>
double dot(const core::data::alias_vec &v1, const arma::Col<T> &v2) {
  double dot_product = 0;
  for(int i = 0; i < static_cast<int>(v2.n_elem); i++) {
    dot_product += v1[i] * v2[i];
  }
  return dot_product;
}

template<typename T>
double dot(const arma::Col<T> &v1, const core::data::alias_vec &v2) {
  double dot_product = 0;
  for(int i = 0; i < static_cast<int>(v1.n_elem); i++) {
    dot_product += v1[i] * v2[i];
  }
  return dot_product;
}

double dot(
  const core::data::alias_vec &v1, const core::data::alias_vec &v2);

void scaled_add(
  double scale_in, const core::data::alias_vec &v1, arma::vec *v2);
}

#endif
